home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-09-02 | 6.0 KB | 193 lines | [TEXT/CCL2] |
- ;;; example.lisp
- ;;;
- ;;; Example file showing one way to save person records
- ;;; in a persistent heap.
-
- (in-package :wood)
-
- ;; define the PERSON class
- (defclass person ()
- ((first-name
- :initarg :first-name
- :accessor person-first-name)
- (last-name
- :initarg :last-name
- :accessor person-last-name)
- (age
- :initarg :age
- :accessor person-age)
- (sex
- :initarg :sex
- :accessor person-sex)
- (occupation
- :initarg :occupation
- :accessor person-occupation)
- (ss#
- :initarg :ss#
- :accessor person-ss#)))
-
- (defmethod person-name ((self person))
- (concatenate 'string (person-first-name self) " " (person-last-name self)))
-
- (defmethod print-object ((object person) stream)
- (print-unreadable-object (object stream :type t :identity t)
- (format stream "~a ~a, ~a"
- (person-first-name object)
- (person-last-name object)
- (person-occupation object))))
-
- ;; Create a persistent heap for storing indexed PERSON instances.
- ;; The root object is a three element list.
- ;; The first element identifies the file.
- ;; The second element is a btree mapping social security number to person.
- ;; The third element is a btree mapping last name to a list of people.
- (defun create-person-file (&key (filename "People.wood")
- (if-exists :error))
- (let ((pheap (open-pheap filename
- :if-exists if-exists
- :if-does-not-exist :create)))
- (setf (root-object pheap)
- (p-list pheap
- "People" ; Identify this file
- (p-make-btree pheap) ; ss# -> person
- (p-make-btree pheap) ; last-name -> (person ...)
- ))
- pheap))
-
- ; I wouldn't really look up the root for every access in a production system.
- (defun person-pheap-tables (pheap)
- (let ((root (p-load (root-object pheap))))
- (unless (and (listp root)
- (eql 3 (length root))
- (equal "People" (first root))
- (p-btree-p (second root))
- (p-btree-p (third root)))
- (error "~s does not appear to be a person file" pheap))
- (values (second root) (third root))))
-
- (defun store-person (pheap person)
- (setq person (require-type person 'person))
- (multiple-value-bind (ss#->person last-name->person-list)
- (person-pheap-tables pheap)
- (let ((ss# (person-ss# person))
- (last-name (string-upcase (person-last-name person))))
- (unless (p-btree-lookup ss#->person ss#)
- (setf (p-btree-lookup ss#->person (person-ss# person)) person
- (p-btree-lookup last-name->person-list last-name)
- (cons person
- (p-load (p-btree-lookup last-name->person-list last-name)))))))
- person)
-
- (defun find-person-with-ss# (pheap ss#)
- (let ((ss#->person (person-pheap-tables pheap)))
- (p-load (p-btree-lookup ss#->person ss#))))
-
- (defun find-people-with-last-name (pheap last-name)
- (multiple-value-bind (ss#->person last-name->person-list)
- (person-pheap-tables pheap)
- (declare (ignore ss#->person))
- (p-load (p-btree-lookup last-name->person-list (string-upcase last-name)))))
-
- (defun print-people-by-ss# (pheap)
- (let ((ss#->person (person-pheap-tables pheap)))
- (p-map-btree ss#->person
- #'(lambda (ss# person)
- (format t "~&~a ~s~%" ss# (p-load person))))))
-
- (defun print-people-by-last-name (pheap)
- (multiple-value-bind (ss#->person last-name->person-list)
- (person-pheap-tables pheap)
- (declare (ignore ss#->person))
- (p-map-btree last-name->person-list
- #'(lambda (last-name person-list)
- (declare (ignore last-name))
- (setq person-list
- (sort (mapcar 'p-load (p-load person-list))
- #'string<
- :key 'person-first-name))
- (dolist (person person-list)
- (format t "~&~s~%" person))))))
-
- ;; Code for creating random PERSON instances.
- (defparameter *first-names*
- '(("Alan" . M)
- ("Abraham" . M)
- ("Andrew" . M)
- ("Alice" . F)
- ("Susan" . F)
- ("Bob" . M)
- ("Hillary" . F)
- ("Joe" . M)
- ("Bill" . M)
- ("Matthew" . M)
- ("Gail" . F)
- ("Gary" . M)
- ("Doug" . M)
- ("Christie" . F)
- ("Steve" . M)
- ("Elizabeth" . F)
- ("Melissa" . F)
- ("Karla" . F)
- ("Dan" . M)
- ("Irving" . M)))
-
- (defparameter *last-names*
- '("Smith" "Jones" "Peterson" "Williams" "Kennedy" "Johnson"
- "Riley" "Sylversteen" "Wilson" "Cranshaw" "Ryan" "O'Neil"
- "McAllister"))
-
- (defparameter *occupations*
- '("Butcher" "Baker" "Candlestick Maker"
- "Engineer" "Hacker" "Tailor" "Cop" "Lawyer" "Doctor"
- "Dentist" "Politician" "Cashier" "Insurance Sales"
- "Advertising"))
-
- (defun random-person ()
- (multiple-value-bind (first-name last-name sex) (random-name)
- (make-instance 'person
- :first-name first-name
- :last-name last-name
- :sex sex
- :age (random 100)
- :occupation (random-element *occupations*)
- :ss# (random-ss#))))
-
- (defun random-element (sequence)
- (elt sequence (random (length sequence))))
-
- (defun random-name ()
- (let ((first.sex (random-element *first-names*))
- (last (random-element *last-names*)))
- (values
- (car first.sex)
- last
- (cdr first.sex))))
-
- (defvar *ss#s* (make-hash-table :test 'equal))
-
- (defun random-ss# ()
- (with-standard-io-syntax
- (loop
- (let ((ss# (write-to-string
- (+ (expt 10 8) (random (- (expt 10 9) (expt 10 8)))))))
- (unless (gethash ss# *ss#s*)
- (return
- (setf (gethash ss# *ss#s*) ss#)))))))
-
- (defun store-n-random-people (pheap n)
- (dotimes (i n)
- (store-person pheap (random-person))))
-
- #|
- (defparameter *p* (create-person-file :if-exists :supersede)
- ; or
- (defparameter *p* (open-pheap "People.wood"))
-
- (store-n-random-people 100)
-
- (print-people-by-ss# *p*)
-
- (print-people-by-last-name *p*)
-
- (close-pheap *p*)
- |#